home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 20 / Cream of the Crop 20 (Terry Blount) (1996).iso / os2 / bind493a.zip / named / dmalloc.c < prev    next >
C/C++ Source or Header  |  1995-12-06  |  8KB  |  315 lines

  1. /* dmalloc - debugging layer on top of malloc
  2.  * vix 25mar92 [fixed bug in round-up calcs in alloc()]
  3.  * vix 24mar92 [added size calcs, improved printout]
  4.  * vix 22mar92 [original work]
  5.  *
  6.  * $Id: dmalloc.c,v 8.2 1995/12/06 20:34:38 vixie Exp $
  7.  */
  8.  
  9. /*
  10.  * ++Copyright++ 1993
  11.  * -
  12.  * Copyright (c) 1993
  13.  *    The Regents of the University of California.  All rights reserved.
  14.  * 
  15.  * Redistribution and use in source and binary forms, with or without
  16.  * modification, are permitted provided that the following conditions
  17.  * are met:
  18.  * 1. Redistributions of source code must retain the above copyright
  19.  *    notice, this list of conditions and the following disclaimer.
  20.  * 2. Redistributions in binary form must reproduce the above copyright
  21.  *    notice, this list of conditions and the following disclaimer in the
  22.  *    documentation and/or other materials provided with the distribution.
  23.  * 3. All advertising materials mentioning features or use of this software
  24.  *    must display the following acknowledgement:
  25.  *     This product includes software developed by the University of
  26.  *     California, Berkeley and its contributors.
  27.  * 4. Neither the name of the University nor the names of its contributors
  28.  *    may be used to endorse or promote products derived from this software
  29.  *    without specific prior written permission.
  30.  * 
  31.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  32.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  33.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  34.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  35.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  39.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  40.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  41.  * SUCH DAMAGE.
  42.  * -
  43.  * Portions Copyright (c) 1993 by Digital Equipment Corporation.
  44.  * 
  45.  * Permission to use, copy, modify, and distribute this software for any
  46.  * purpose with or without fee is hereby granted, provided that the above
  47.  * copyright notice and this permission notice appear in all copies, and that
  48.  * the name of Digital Equipment Corporation not be used in advertising or
  49.  * publicity pertaining to distribution of the document or software without
  50.  * specific, written prior permission.
  51.  * 
  52.  * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
  53.  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
  54.  * OF MERCHANTABILITY AND FITNESS.   IN NO EVENT SHALL DIGITAL EQUIPMENT
  55.  * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  56.  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  57.  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
  58.  * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  59.  * SOFTWARE.
  60.  * -
  61.  * --Copyright--
  62.  */
  63.  
  64. #include <stdio.h>
  65. #include <signal.h>
  66. #include "../conf/portability.h"
  67. #include "../conf/options.h"
  68.  
  69. #ifdef DMALLOC
  70.  
  71. #define TRUE 1
  72. #define FALSE 0
  73. typedef    unsigned bool;
  74.  
  75. #define    MAX_MEMORY    65536    /* must fit in typeof(datum.size) */
  76. #define    MAX_CALLERS    256    /* must be **2 */
  77.  
  78. typedef struct caller {
  79.     struct caller    *next;
  80.     struct filenam    *file;
  81.     struct calltab    *frees;
  82.     unsigned    line;
  83.     unsigned    calls;
  84.     unsigned    blocks;
  85.     unsigned    bytes;
  86. } caller;
  87.  
  88. typedef    struct filenam {
  89.     struct filenam    *next;
  90.     char        *name;
  91. } filenam;
  92.  
  93. typedef    struct calltab {
  94.     struct caller    *callers[MAX_CALLERS];
  95. } calltab;
  96.  
  97. typedef struct datum {
  98.     unsigned    size;        /* size of malloc'd item */
  99.     unsigned    caller;        /* offset into memory[] */
  100.     /* user data follows */
  101. } datum;
  102.  
  103. static    char    memory[MAX_MEMORY];
  104. static    char    *nextmem = memory;
  105. static    char    *alloc(size) unsigned size; {
  106.             char *thismem = nextmem;
  107.             int oddness = (size % sizeof(char*));
  108.             if (oddness)
  109.                 size += (sizeof(char*) - oddness);
  110.             nextmem += size;
  111.             if (nextmem >= &memory[MAX_MEMORY]) {
  112.                 fprintf(stderr, "dmalloc.alloc: out of mem\n");
  113.                 kill(0, SIGBUS);
  114.             }
  115.             return thismem;
  116.         }
  117.  
  118. static    filenam    *Files;
  119. static    calltab    Callers;
  120.  
  121. /*--------------------------------------------------- imports
  122.  */
  123.  
  124. #undef    malloc
  125. #undef    calloc
  126. #undef    realloc
  127. #undef    free
  128.  
  129. char    *malloc(), *calloc(), *realloc();
  130.  
  131. #if    defined(sun)
  132. int    free();
  133. #else
  134. void    free();
  135. #endif
  136.  
  137. /*--------------------------------------------------- private
  138.  */
  139.  
  140. #define    STR_EQ(l,r)    (((l)[0] == (r)[0]) && !strcmp(l, r))
  141.  
  142. static filenam *
  143. findFile(file, addflag)
  144.     char *file;
  145.     bool addflag;
  146. {
  147.     filenam    *f;
  148.  
  149.     for (f = Files;  f;  f = f->next)
  150.         if (STR_EQ(file, f->name))
  151.             return f;
  152.     if (!addflag)
  153.         return NULL;
  154.     f = (filenam*) alloc(sizeof(filenam));
  155.     f->next = Files;
  156.     Files = f;
  157.     f->name = alloc(strlen(file) + 1);
  158.     strcpy(f->name, file);
  159.     return f;
  160. }
  161.  
  162. static caller *
  163. findCaller(ctab, file, line, addflag)
  164.     calltab *ctab;
  165.     char *file;
  166.     unsigned line;
  167.     bool addflag;
  168. {
  169.     unsigned hash = line & (MAX_CALLERS - 1);
  170.     caller *c;
  171.  
  172.     for (c = ctab->callers[hash];  c;  c = c->next)
  173.         if ((c->line == line) && STR_EQ(c->file->name, file))
  174.             return c;
  175.     if (!addflag)
  176.         return NULL;
  177.     c = (caller*) alloc(sizeof(caller));
  178.     c->next = ctab->callers[hash];
  179.     c->file = findFile(file, TRUE);
  180.     c->line = line;
  181.     c->calls = 0;
  182.     c->frees = (calltab *) alloc(sizeof(calltab));
  183.     ctab->callers[hash] = c;
  184.     return c;
  185. }
  186.  
  187. /*--------------------------------------------------- public
  188.  */
  189.  
  190. char *
  191. dmalloc(file, line, size)
  192.     char *file;
  193.     unsigned line;
  194.     unsigned size;
  195. {
  196.     caller *c;
  197.     datum *d;
  198.  
  199.     c = findCaller(&Callers, file, line, TRUE);
  200.     d = (datum *) malloc(sizeof(datum) + size);
  201.     if (!d)
  202.         return (NULL);
  203.     d->size = size;
  204.     d->caller = ((char *)c) - memory;
  205.     c->calls++;
  206.     c->blocks++;
  207.     c->bytes += size;
  208.     return (char *) (d+1);
  209. }
  210.  
  211. void
  212. dfree(file, line, ptr)
  213.     char *file;
  214.     unsigned line;
  215.     char *ptr;
  216. {
  217.     caller *c, *a;
  218.     datum *d;
  219.  
  220.     d = (datum *) ptr;  d--;
  221.     a = (caller *) (memory + d->caller);
  222.     a->bytes -= d->size;
  223.     a->blocks--;
  224.     c = findCaller(a->frees, file, line, TRUE);
  225.     c->calls++;
  226.     free((char*) d);
  227. }
  228.  
  229. char *
  230. dcalloc(file, line, nelems, elsize)
  231.     char *file;
  232.     unsigned line;
  233.     unsigned nelems, elsize;
  234. {
  235.     unsigned size = (nelems * elsize);
  236.     char *ptr;
  237.  
  238.     ptr = dmalloc(file, line, size);
  239.     bzero(ptr, size);
  240.     return ptr;
  241. }
  242.  
  243. char *
  244. drealloc(file, line, ptr, size)
  245.     char *file;
  246.     unsigned line;
  247.     char *ptr;
  248.     unsigned size;
  249. {
  250.     caller *c, *a;
  251.     datum *d;
  252.  
  253.     d = (datum *) ptr;  d--;
  254.     /* fix up stats from allocation */
  255.     a = (caller *) (memory + d->caller);
  256.     a->bytes -= d->size;
  257.     a->blocks--;
  258.     /* we are a "freer" of this allocation */
  259.     c = findCaller(a->frees, file, line, TRUE);
  260.     c->calls++;
  261.     /* get new allocation and stat it */
  262.     c = findCaller(&Callers, file, line, TRUE);
  263.     d = (datum *) realloc((char *) d, sizeof(datum) + size);
  264.     d->size = size;
  265.     d->caller = ((char *)c) - memory;
  266.     c->calls++;
  267.     c->blocks++;
  268.     c->bytes += size;
  269.     return (char *) (d+1);
  270. }
  271.  
  272. static void
  273. dmalloccallers(outf, prefix, ctab)
  274.     FILE *outf;
  275.     char *prefix;
  276.     calltab *ctab;
  277. {
  278.     /* this bizarre logic is to print all of a file's entries together */
  279.     filenam    *f;
  280.  
  281.     for (f = Files;  f;  f = f->next) {
  282.         int    i;
  283.  
  284.         for (i = MAX_CALLERS-1;  i >= 0;  i--) {
  285.             caller *c;
  286.  
  287.             for (c = ctab->callers[i];  c;  c = c->next) {
  288.                 if (f != c->file)
  289.                     continue;
  290.                 fprintf(outf, "%s\"%s\":%u calls=%u",
  291.                     prefix, c->file->name, c->line,
  292.                     c->calls);
  293.                 if (c->blocks || c->bytes)
  294.                     fprintf(outf, " blocks=%u bytes=%u",
  295.                         c->blocks, c->bytes);
  296.                 fputc('\n', outf);
  297.                 if (c->frees)
  298.                     dmalloccallers(outf,
  299.                                "\t\t", c->frees);
  300.             }
  301.         }
  302.     }
  303. }
  304.  
  305. void
  306. dmallocstats(outf)
  307.     FILE *outf;
  308. {
  309.     fprintf(outf, "dallocstats [ private mem used=%u, avail=%u ]\n",
  310.         nextmem - memory, &memory[MAX_MEMORY] - nextmem);
  311.     dmalloccallers(outf, "\t", &Callers);
  312. }
  313.  
  314. #endif /*DMALLOC*/
  315.